﻿#region Usings

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;

#endregion

namespace xConnected.ActionFilter
{
    public class SetCultureAttribute : FilterAttribute, IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string cultureCode = SetCurrentLanguage(filterContext);

            if (string.IsNullOrEmpty(cultureCode)) return;

            HttpContext.Current.Response.Cookies.Add(
                new HttpCookie("Culture", cultureCode)
                    {
                        HttpOnly = true,
                        Expires = DateTime.Now.AddYears(100)
                    }
                );

            filterContext.HttpContext.Session["Culture"] = cultureCode;

            var culture = new CultureInfo(cultureCode);
            Thread.CurrentThread.CurrentCulture =
                culture;
            Thread.CurrentThread.CurrentUICulture =
                culture;
        }

        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
        }

        private static string GetCookieCulture(ActionExecutingContext filterContext, ICollection<string> cultures)
        {
            //Get the language(the culture) in the cookie
            HttpCookie userCookie = filterContext.RequestContext
                .HttpContext
                .Request
                .Cookies["Culture"];

            if (userCookie != null)
            {
                if (!string.IsNullOrEmpty(userCookie.Value))
                {
                    //if the list of implemented cultures contains the culture of the cookie
                    if (cultures.Contains(userCookie.Value))
                    {
                        return userCookie.Value;
                    }
                    return string.Empty;
                }
                return string.Empty;
            }
            return string.Empty;
        }

        private static string GetSessionCulture(ActionExecutingContext filterContext, ICollection<string> cultures)
        {
            if (filterContext.RequestContext.HttpContext.Session["Culture"] != null)
            {
                string SessionCulture = filterContext.RequestContext
                    .HttpContext
                    .Session["Culture"]
                    .ToString();

                if (!string.IsNullOrEmpty(SessionCulture))
                {
                    //if the list of implemented cultures contains the session culture
                    return cultures.Contains(SessionCulture)
                               ? SessionCulture
                               : string.Empty;
                }
                return string.Empty;
            }
            return string.Empty;
        }

        private static string GetBrowserCulture(ActionExecutingContext
                                                    filterContext, IEnumerable<string> cultures)
        {
            // Gets Languages from Browser
            IList<string> browserLanguages = filterContext.RequestContext
                .HttpContext
                .Request
                .UserLanguages;

            if (browserLanguages != null)
            {
                foreach (var thisCultureLanguage in browserLanguages.SelectMany(thisBrowserLanguage => cultures.Where(thisCultureLanguage => thisCultureLanguage == thisBrowserLanguage)))
                {
                    return thisCultureLanguage;
                }
            }
            return string.Empty;
        }

        private static string SetCurrentLanguage(ActionExecutingContext filterContext)
        {
            //list of implemented cultures(languages)
            IList<string> cultures = new List<string>
                                         {
                                             "en",
                                             "de",
                                             "hr"
                                         };

            //take the culture from the cookie
            var cookieValue = GetCookieCulture(filterContext, cultures);

            //if the value of the cookie is null or empty
            if (string.IsNullOrEmpty(cookieValue))
            {
                //take the culture from the session
                var sessionValue = GetSessionCulture(filterContext, cultures);

                //if the value of the session is null ir empty
                if (string.IsNullOrEmpty(sessionValue))
                {
                    //take the culture from the browser
                    string browserCulture = GetBrowserCulture(filterContext, cultures);

                    //if the culture from the browser is null or empty
                    return string.IsNullOrEmpty(browserCulture)
                           //take "en" as default culture
                               ? "en"
                               : browserCulture;
                }
                return sessionValue;
            }
            return cookieValue;
        }
    }
}